// SkypePluginB.cpp : Implementation of CSkypePluginB

#include "stdafx.h"
#define max std::max
#define min std::min
#include <wtl/atlctrlx.h>
#undef max
#undef min
#include "SkypePluginB.h"
#include "OptionsSkype.h"

#define SKYPE_API_KEY "AQIAALdzfvWyYizWDkG2pTyHRj9tqNLj"
#define SKYPE_REFERRER "SkypePlugin"


class CSkypeHyperLink : public CHyperLinkImpl<CSkypeHyperLink>
{
public:
	DECLARE_WND_CLASS(_T("HyperLink"))

	CSkypeHyperLink() : CHyperLinkImpl(HLINK_COMMANDBUTTON)
	{}
};

CSkypePluginB::CSkypePluginB()
	: CPluginBase(SKYPE_API_KEY, SKYPE_REFERRER)
	, m_hMainSkypeWindow(NULL)
	, m_ctl(this)
{
}

static DWORD WINAPI
SkypeWorkerThreadProc(LPVOID lpParameter)
{
	CSkypePluginB *pThis = (CSkypePluginB*)lpParameter;
	ATLTRACE(_T("Start thread\n"));

	// Initialize messaging system.
	//
	PostThreadMessage(::GetCurrentThreadId(), WM_NULL, 0, 0);

	return pThis->Process();
}

DWORD WINAPI
CSkypePluginB::Process()
{
	HTL::CWaitableTimer hTimer(FALSE);

	if (!hTimer.Set(0LL, POLLING_PERIOD))
	{
		Error(_T("Timer problem"));
		return 1;
	}

	if (!m_ctl.Create(HWND_MESSAGE, ATL::CWindow::rcDefault))
	{
		Error(_T("Notify window problem"));
		return 2;
	}

	if (!m_ctl.Discover())
	{
		Error(_T("Skype attach failed"));
		return 3;
	}

	Login();

	HANDLE rgHandles[] = { hTimer, m_hShutdownEvent };

	while (m_ctl.GetStatus() != apiAttachRefused)
	{
		DWORD dwWait = ::MsgWaitForMultipleObjectsEx(ARRAYSIZE(rgHandles),
			rgHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE);

		// Stop signalled
		//
		if ((WAIT_OBJECT_0 + 1) == dwWait)
			break;

		// Timer event
		//
		if ((WAIT_OBJECT_0 + 0) == dwWait)
		{
			m_scanner.SetLang(m_ctl.GetUserLanguages());
			OnSetLocation(GetLocation(FMT_XHTML));
			continue;
		}

		// A windows message has been arrived
		MSG msg;
		while(::PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
		{
			::TranslateMessage(&msg);
			::DispatchMessage(&msg);
		}
	}

	ATLTRACE(_T("Exit thread, status %d\n"), m_ctl.GetStatus());
	m_ctl.DestroyWindow();

	return 0;
}

STDMETHODIMP
CSkypePluginB::Open
	( IN POPEN_CONTEXT pOpenContext
	)
{
	ATLTRACE(_T(__FUNCTION__) _T(": 0x%08X\n"), pOpenContext);

	if (pOpenContext == NULL)
		return E_INVALIDARG;

	ATLTRACE(_T("Context: ContextType=%d, ContextRef=%ls, Participants=%ls, UniqueID=%ls\n")
		, pOpenContext->ContextType
		, pOpenContext->wzContextRef
		, pOpenContext->wzParticipants
		, pOpenContext->wzUniqueID
		);

	// Start();
	if (!m_hPollingThread)
	{
		m_hShutdownEvent.Create(FALSE, FALSE);

		DWORD dwThreadId;
		m_hPollingThread.Create(SkypeWorkerThreadProc, this, 0, &dwThreadId);
		ATLTRACE(_T("Worker thread id %d\n"), dwThreadId);
	}

	if (ctTools == pOpenContext->ContextType)
	{
		ShowSettingsDlg(NULL);
	}

	return S_OK;
}

STDMETHODIMP
CSkypePluginB::ShowSettingsDlg
	( IN OLE_HANDLE hWndOwner
	)
{
	// Register the HyperLink class
	//
	CSkypeHyperLink a;
	a.Create(NULL);

	CSkypeOptions dlgOptions;
	HWND hWnd = hWndOwner? (HWND)IntToPtr(hWndOwner): ::GetActiveWindow();
	INT_PTR nRet = dlgOptions.DoModal(hWnd, (LPARAM)this);
	if (IDOK == nRet)
		Login();

	return S_OK;
}

STDMETHODIMP
CSkypePluginB::Finalize()
{
	ATLTRACE(_T(__FUNCTION__) _T("\n"));

	m_ctl.PostMessage(WM_CLOSE);

	Stop();
	return S_OK;
}

const _tstring
CSkypePluginB::ReadIniFileSetings
	( IN LPCTSTR szName
	) const
{
	std::string strUserName = m_ctl.GetUser();
	if (strUserName.empty())
		return _T("");

	TCHAR szValue[64] = _T("");
	TCHAR szPath[MAX_PATH];
	if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_APPDATA, TRUE))
	{
		_tcscat(szPath, _T("\\"));
		_tcscat(szPath, ATL::CA2TEX<64>(strUserName.c_str(), CP_UTF8));
		_tcscat(szPath, _T(".wi2geo.plugin.ini"));

		::GetPrivateProfileString (_T("GeoSkype"), szName, _T(""), szValue, ARRAYSIZE(szValue), szPath);
	}

	return szValue;
}

void
CSkypePluginB::WriteIniFileSetings
	( IN LPCTSTR szName
	, IN _tstring strValue
	) const
{
	std::string strUserName = m_ctl.GetUser();
	if (strUserName.empty())
		return;

	TCHAR szPath[MAX_PATH];
	if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_APPDATA, TRUE))
	{
		_tcscat(szPath, _T("\\"));
		_tcscat(szPath, ATL::CA2TEX<64>(strUserName.c_str(), CP_UTF8));
		_tcscat(szPath, _T(".wi2geo.plugin.ini"));

		::WritePrivateProfileString (_T("GeoSkype"), szName, strValue.c_str(), szPath);
	}
}

EXTERN_C VOID WINAPI
DllInitSkypePluginB
	( IN const BSTR wzItemID
	, IN ICollectionManager *pColManager
	, OUT ISkypePluginB **ppPlugin
	, IN const BSTR wzParams
	)
{
	ATLTRACE(_T(__FUNCTION__) _T(": %ls, 0x%08X, 0x%08X, %ls\n")
		, wzItemID, pColManager, ppPlugin, wzParams);

	CoSkypePluginB *pPlugin;
	HRESULT hr;

	hr = CoSkypePluginB::CreateInstance(&pPlugin);
	if (SUCCEEDED(hr))
	{
		pPlugin->AddRef();
		hr = pPlugin->Init(wzItemID, pColManager, wzParams);
		if (SUCCEEDED(hr))
			pPlugin->QueryInterface(ppPlugin);
		pPlugin->Release();
	}

	if (FAILED(hr))
		ATLTRACE(_T("Failed to create plugin: 0x%08X\n"), hr);
}
